package com.lwq.nacos.grayscale.gray;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Optional;
import com.lwq.nacos.grayscale.constants.Constants;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * 根据nacos metadata 选择对应的服务
 */
@Slf4j
public class CustomNacosMetadataRule extends ZoneAvoidanceRule {

    @Override
    public Server choose(Object key) {
        NacosMetaDataContext context = NacosMetaDataContextHolder.getContext();
        Map<String, String> attributes = context.getNacosMateMap();
        String grayName = attributes.get(Constants.GRAY_HEADER_NAME);
        // 所有的服务列表
        List<Server> allServerList = getLoadBalancer().getAllServers();
        if (CollectionUtil.isEmpty(allServerList)){
            return null;
        }

        // 匹配meta信息成功的服务
        List<Server> matchedServerList = new ArrayList<>();
        // 匹配meta信息未成功的服务
        List<Server> notMatchedServerList = new ArrayList<>();
        // 执行匹配
        doMatches(grayName, allServerList, matchedServerList, notMatchedServerList);

        // 先执行匹配成功的服务
        if (!matchedServerList.isEmpty()) {
            Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(matchedServerList, key);
            if (server.isPresent()) {
                return server.get();
            }
        }

        // 再走未匹配成功的服务
        if (!notMatchedServerList.isEmpty()) {
            Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(notMatchedServerList, key);
            if (server.isPresent()) {
                return server.get();
            }
        }
        return null;
    }

    /**
     * 执行匹配
     *
     * @param grayName 需要匹配的名称
     * @param allServerList 所有的服务列表
     * @param matchedServerList 匹配成功的服务列表
     * @param notMatchedServerList 未匹配成功的服务列表
     */
    private void doMatches(String grayName, List<Server> allServerList, List<Server> matchedServerList, List<Server> notMatchedServerList) {
        for (Server server : allServerList) {
            if (! (server instanceof NacosServer)) {
                continue;
            }
            NacosServer nacosServer = (NacosServer) server;
            Map<String, String> metadata = nacosServer.getMetadata();
            String metaGrayName = metadata.get(Constants.GRAY_HEADER_NAME);
            if (StrUtil.isBlank(metaGrayName)) {
                // 未匹配成功
                notMatchedServerList.add(server);
            } else {
                if (StrUtil.isNotBlank(grayName) &&  StrUtil.equals(grayName, metaGrayName)) {
                    // 匹配成功
                    matchedServerList.add(server);
                }else{
                    notMatchedServerList.add(server);
                }
            }
        }
    }
}